<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Node 第 4 天 | Megasu的笔记</title>
    <meta name="generator" content="VuePress 1.5.4">
    <link rel="icon" href="/heima2020/favicon.ico">
    <meta name="description" content="Megasu的笔记整理">
    <meta name="author" content="Megasu">
    <meta name="Keywords" content="学习网站,前端,分享">
    <link rel="preload" href="/heima2020/assets/css/0.styles.aa663799.css" as="style"><link rel="preload" href="/heima2020/assets/js/app.e2adc9d2.js" as="script"><link rel="preload" href="/heima2020/assets/js/2.7389c9d3.js" as="script"><link rel="preload" href="/heima2020/assets/js/5.6eb7e243.js" as="script"><link rel="prefetch" href="/heima2020/assets/js/10.8b750e5f.js"><link rel="prefetch" href="/heima2020/assets/js/11.9224f975.js"><link rel="prefetch" href="/heima2020/assets/js/12.3ea117b6.js"><link rel="prefetch" href="/heima2020/assets/js/13.7524b74f.js"><link rel="prefetch" href="/heima2020/assets/js/14.cee0fcf8.js"><link rel="prefetch" href="/heima2020/assets/js/15.7a4a27f7.js"><link rel="prefetch" href="/heima2020/assets/js/16.947d882b.js"><link rel="prefetch" href="/heima2020/assets/js/17.79d3becb.js"><link rel="prefetch" href="/heima2020/assets/js/18.48208e3a.js"><link rel="prefetch" href="/heima2020/assets/js/19.3d0c49ef.js"><link rel="prefetch" href="/heima2020/assets/js/20.1f6114c8.js"><link rel="prefetch" href="/heima2020/assets/js/21.85e67b4a.js"><link rel="prefetch" href="/heima2020/assets/js/22.ce482f4d.js"><link rel="prefetch" href="/heima2020/assets/js/23.a150bd35.js"><link rel="prefetch" href="/heima2020/assets/js/24.8cd80d5d.js"><link rel="prefetch" href="/heima2020/assets/js/25.0001c7c1.js"><link rel="prefetch" href="/heima2020/assets/js/26.aa4d65a5.js"><link rel="prefetch" href="/heima2020/assets/js/27.baffff1d.js"><link rel="prefetch" href="/heima2020/assets/js/28.20430dcf.js"><link rel="prefetch" href="/heima2020/assets/js/29.7bbc3c04.js"><link rel="prefetch" href="/heima2020/assets/js/3.0076a912.js"><link rel="prefetch" href="/heima2020/assets/js/30.5f74696f.js"><link rel="prefetch" href="/heima2020/assets/js/31.a0bf56d6.js"><link rel="prefetch" href="/heima2020/assets/js/32.dd5a93dd.js"><link rel="prefetch" href="/heima2020/assets/js/33.92de7335.js"><link rel="prefetch" href="/heima2020/assets/js/34.bf468ed6.js"><link rel="prefetch" href="/heima2020/assets/js/35.28502be1.js"><link rel="prefetch" href="/heima2020/assets/js/36.3622a14c.js"><link rel="prefetch" href="/heima2020/assets/js/37.626e17d3.js"><link rel="prefetch" href="/heima2020/assets/js/38.860020b8.js"><link rel="prefetch" href="/heima2020/assets/js/39.c092c283.js"><link rel="prefetch" href="/heima2020/assets/js/4.586af112.js"><link rel="prefetch" href="/heima2020/assets/js/40.a6ba2743.js"><link rel="prefetch" href="/heima2020/assets/js/41.43d70bcd.js"><link rel="prefetch" href="/heima2020/assets/js/42.6486a709.js"><link rel="prefetch" href="/heima2020/assets/js/43.670b256a.js"><link rel="prefetch" href="/heima2020/assets/js/44.eb371480.js"><link rel="prefetch" href="/heima2020/assets/js/45.5b45f11e.js"><link rel="prefetch" href="/heima2020/assets/js/46.bc59be94.js"><link rel="prefetch" href="/heima2020/assets/js/47.ec36fca9.js"><link rel="prefetch" href="/heima2020/assets/js/48.51e80f8f.js"><link rel="prefetch" href="/heima2020/assets/js/6.1b7d5a6d.js"><link rel="prefetch" href="/heima2020/assets/js/7.f611fe3c.js"><link rel="prefetch" href="/heima2020/assets/js/8.c14cc922.js"><link rel="prefetch" href="/heima2020/assets/js/9.cd5538bb.js">
    <link rel="stylesheet" href="/heima2020/assets/css/0.styles.aa663799.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/heima2020/" class="home-link router-link-active"><!----> <span class="site-name">Megasu的笔记</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/heima2020/" class="nav-link">
  首页
</a></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/heima2020/" class="nav-link">
  首页
</a></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><a href="/heima2020/node/day01" class="sidebar-heading clickable open"><span>Node</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/heima2020/node/day01.html" class="sidebar-link">Node 第 1 天</a></li><li><a href="/heima2020/node/day02.html" class="sidebar-link">Node 第 2 天</a></li><li><a href="/heima2020/node/day03.html" class="sidebar-link">Node 第 3 天</a></li><li><a href="/heima2020/node/day04.html" aria-current="page" class="active sidebar-link">Node 第 4 天</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#node-第-4-天" class="sidebar-link">Node 第 4 天</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_1-学习目标" class="sidebar-link">1.  学习目标</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_2-express-路由" class="sidebar-link">2. Express 路由</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_3-中间件" class="sidebar-link">3. 中间件</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_4-中间件的分类" class="sidebar-link">4. 中间件的分类</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_5-自定义中间件" class="sidebar-link">5. 自定义中间件</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_6-基于-express-写接口" class="sidebar-link">6. 基于 Express 写接口</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_7-cors" class="sidebar-link">7. cors</a></li><li class="sidebar-sub-header"><a href="/heima2020/node/day04.html#_8-jsonp" class="sidebar-link">8. jsonp</a></li></ul></li></ul></li><li><a href="/heima2020/node/day05.html" class="sidebar-link">Node 第 5 天</a></li><li><a href="/heima2020/node/day06.html" class="sidebar-link">Node 第 6 天</a></li><li><a href="/heima2020/node/day07.html" class="sidebar-link">Node 第 7 天</a></li><li><a href="/heima2020/node/day08.html" class="sidebar-link">Node 第 8 天</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h2 id="node-第-4-天"><a href="#node-第-4-天" class="header-anchor">#</a> Node 第 4 天</h2> <h3 id="_1-学习目标"><a href="#_1-学习目标" class="header-anchor">#</a> 1.  学习目标</h3> <p>◆  能够熟练 express 路由的使用</p> <p>◆  掌握中间件的使用方式</p> <p>◆  能够说出中间件分为哪几类</p> <p>◆  了解如何自定义中间件</p> <p>◆  能够基于 exprss 写接口</p> <p>◆  能够说出解决跨域问题的方法 cors</p> <p>◆  掌握如何实现 JSONP 接口</p> <h3 id="_2-express-路由"><a href="#_2-express-路由" class="header-anchor">#</a> 2. Express 路由</h3> <h4 id="_2-1-路由的概念"><a href="#_2-1-路由的概念" class="header-anchor">#</a> 2.1 路由的概念</h4> <ol><li><p>路由就是<strong>映射关系</strong></p></li> <li><p>根据不同的用户 URL 请求，返回不同的内容</p></li> <li><p>本质：URL 请求地址与服务器资源之间的对应关系</p></li></ol> <div class="language- extra-class"><pre><code>  &lt;img src=&quot;./images/Day_004/001 - 路由.png&quot; style=&quot;zoom:67%;&quot; /&gt;
</code></pre></div><h4 id="_2-2-express-中的路由"><a href="#_2-2-express-中的路由" class="header-anchor">#</a> 2.2 Express 中的路由</h4> <ol><li><p>在 <code>Express</code> 中，路由指的是<strong>客户端的请求</strong>与<strong>服务器处理函数</strong>之间的<strong>映射关系</strong></p></li> <li><p>Express 中的路由分 3 部分组成，分别是<strong>请求的类型</strong>、<strong>请求的 URL 地址</strong>、<strong>处理函数</strong></p> <img src="/heima2020/assets/img/002 - express中的路由.92b076cd.png" style="zoom:67%;"></li> <li><p>Express 中的路由的例子</p></li></ol> <img src="/heima2020/assets/img/003 - Express 中的路由的例子.47291de5.png" style="zoom:67%;"> <h4 id="_2-3-路由的匹配过程"><a href="#_2-3-路由的匹配过程" class="header-anchor">#</a> 2.3 路由的匹配过程</h4> <ol><li><p>每当一个请求到达服务器之后，<strong>需要先经过路由的匹配</strong>，只有匹配成功之后，才会调用对应的处理函数</p></li> <li><p>在匹配时，会按照路由的顺序进行匹配，如果<strong>请求类型</strong>和**请求的 URL **同时匹配成功，则 <code>Express</code> 会将这次请求，转交给对应的 function 函数进行处理</p></li></ol> <img src="/heima2020/assets/img/004 - 路由的匹配过程.d4b0d09d.png" style="zoom:67%;"> <ol start="3"><li>路由匹配的注意点</li></ol> <ul><li>按照定义的<strong>先后顺序</strong>进行匹配</li> <li><strong>请求类型</strong>和<strong>请求的URL</strong>同时匹配成功，才会调用对应的处理函数</li></ul> <h4 id="_2-4-express-路由最简单的用法"><a href="#_2-4-express-路由最简单的用法" class="header-anchor">#</a> 2.4 Express 路由最简单的用法</h4> <ol><li><p>在 <code>Express</code> 中使用路由最简单的方式，就是把路由挂载到 <code>app</code> 上</p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 web 服务器，命名为 app</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 挂载路由</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Hello, World'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Hello, Tom'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_2-5-模块化路由"><a href="#_2-5-模块化路由" class="header-anchor">#</a> 2.5 模块化路由</h4> <ol><li>为了方便对路由进行模块化的管理，<code>Express</code> 不建议将路由直接挂载到 <code>app</code> 上，而是推荐将路由抽离为单独的模块，将路由抽离为单独模块的步骤如下</li></ol> <ul><li><p>创建路由模块对应的 <code>.js</code> 文件</p></li> <li><p>调用 <code>express.Router()</code>函数创建路由对象</p></li> <li><p>向路由对象上挂载具体的路由</p></li> <li><p>使用 <code>module.exports</code> 向外共享路由对象</p></li> <li><p>使用 <code>app.use()</code> 函数注册路由模块</p></li></ul> <ol start="2"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 1. 导入 express</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 2. 创建路由对象</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 3. 挂载获取用户列表的路由</span>
router<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user/list'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'用户列表'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 4. 挂载添加用户列表的路由</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/user/add'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'添加用户'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 5. 向外导出路由对象</span>
module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><h4 id="_2-6-注册路由模块"><a href="#_2-6-注册路由模块" class="header-anchor">#</a> 2.6 注册路由模块</h4> <ol><li><p>导入路由模块</p></li> <li><p>使用 <code>app.use()</code> 注册路由模块</p></li> <li><p>案例代码</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入路由模块</span>
<span class="token keyword">const</span> userRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./002-router'</span><span class="token punctuation">)</span>

<span class="token comment">// 使用 app.use() 注册路由模块</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>userRouter<span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div></li></ol> <h4 id="_2-7-为路由模块添加前缀"><a href="#_2-7-为路由模块添加前缀" class="header-anchor">#</a> 2.7 为路由模块添加前缀</h4> <ol><li><p>类似于托管静态资源写法，为静态资源统一挂载访问前缀一样</p></li> <li><p>注意，添加了路由前缀后，访问的路由的时候，也应该加上前缀</p></li> <li><p>案例代码</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入路由模块</span>
<span class="token keyword">const</span> userRouter <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./002-router'</span><span class="token punctuation">)</span>

<span class="token comment">// 使用 app.use() 注册路由模块</span>
<span class="token comment">// 给路由模块添加统一得到访问前缀 /api</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> userRouter<span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div></li></ol> <h3 id="_3-中间件"><a href="#_3-中间件" class="header-anchor">#</a> 3. 中间件</h3> <h4 id="_3-1-中间件的概念"><a href="#_3-1-中间件的概念" class="header-anchor">#</a> 3.1 中间件的概念</h4> <ol><li>什么是中间件</li></ol> <p>所谓的中间件（<code>Middleware</code> ），特指业务流程的中间处理环节</p> <ol start="2"><li>现实生活中的例子</li></ol> <p>在处理污水的时候，一般都要经过三个处理环节，从而保证处理过后的废水，达到排放标准</p> <p>处理污水的这三个中间处理环节，就可以叫做中间件</p> <img src="/heima2020/assets/img/005 - 中间件.eaa7c540.png" alt="中间件" style="zoom:67%;"> <h4 id="_3-2-express-中间件的调用流程"><a href="#_3-2-express-中间件的调用流程" class="header-anchor">#</a> 3.2 Express 中间件的调用流程</h4> <p>当一个请求到达 Express 的服务器之后，可以连续调用多个中间件，从而对这次请求进行预处理</p> <img src="/heima2020/assets/img/006 - 中间件的调用流程.722a5311.png" alt="中间件的调用流程" style="zoom:67%;"> <h4 id="_3-3-express-中间件的格式"><a href="#_3-3-express-中间件的格式" class="header-anchor">#</a> 3.3 Express 中间件的格式</h4> <ol><li>Express 的中间件，<strong>本质上就是一个 <code>function</code> 处理函数</strong>，<code>Express</code> 中间件的格式如下</li></ol> <img src="/heima2020/assets/img/007 - Express 中间件的格式.79aaad64.png" style="zoom:67%;"> <ol start="2"><li>注意：中间件函数的形参列表中，<strong>必须包含 next 参数</strong>。而路由处理函数中只包含 <code>req</code> 和 <code>res</code></li></ol> <h4 id="_3-4-next-函数的作用"><a href="#_3-4-next-函数的作用" class="header-anchor">#</a> 3.4 next 函数的作用</h4> <p><strong>next 函数</strong>是实现<strong>多个中间件连续调用</strong>的关键，它表示把流转关系<strong>转交</strong>给下一个<strong>中间件</strong>或<strong>路由</strong></p> <img src="/heima2020/assets/img/008 - next 函数的作用.374927b4.png" style="zoom:67%;"> <h4 id="_3-5-定义中间件函数"><a href="#_3-5-定义中间件函数" class="header-anchor">#</a> 3.5  定义中间件函数</h4> <ul><li><p>定义一个最简单的中间件函数</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 定义一个最简单的中间件函数</span>
<span class="token keyword">const</span> <span class="token function-variable function">kw</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'这是最简单的中间件函数'</span><span class="token punctuation">)</span>

  <span class="token comment">// 把流转关系，转交给下一个中间件或者路由</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">80</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div></li></ul> <h4 id="_3-6-全局生效的中间件"><a href="#_3-6-全局生效的中间件" class="header-anchor">#</a> 3.6 全局生效的中间件</h4> <ol><li><p>客户端发起的<strong>任何请求</strong>，到达服务器之后，都会触发的中间件，叫做全局生效的中间件</p></li> <li><p>通过调用 <code>app.use(中间件函数)</code>，即可顶一个全局生效的中间件</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 定义一个最简单的中间件函数</span>
<span class="token keyword">const</span> <span class="token function-variable function">kw</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'这是最简单的中间件函数'</span><span class="token punctuation">)</span>

  <span class="token comment">// 把流转关系，转交给下一个中间件或者路由</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// 全局生效的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>kw<span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'调用了 / 这个路由'</span><span class="token punctuation">)</span>
  
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'调用了 /user 这个路由'</span><span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'User page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_3-7-定义全局中间件的简化形式"><a href="#_3-7-定义全局中间件的简化形式" class="header-anchor">#</a> 3.7 定义全局中间件的简化形式</h4> <ol><li>定义全局中间件也可以将中间件函数直接挂载到 <code>app.use()</code> 上面</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 定义全局中间件的简化形式</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'定义全局中间件的简化形式'</span><span class="token punctuation">)</span>

  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'调用了 / 这个路由'</span><span class="token punctuation">)</span>
  
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'调用了 /user 这个路由'</span><span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'User page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_3-8-中间件的作用"><a href="#_3-8-中间件的作用" class="header-anchor">#</a> 3.8 中间件的作用</h4> <ol><li>多个中间件之间，共享同一份 <code>req</code> 和 <code>res</code>，基于这样的特性，我们可以在<strong>上游</strong> 的中间件中，统一为 <code>req</code> 或 <code>res</code> 对象添加自定义的属性和方法，供下游的中间件或路由进行使用</li></ol> <img src="/heima2020/assets/img/009 - 中间件的作用.dda595ad.png" style="zoom:67%;"> <ol start="2"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 定义全局中间件的简化形式</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 获取到请求达到服务器的时间</span>
  <span class="token keyword">const</span> time <span class="token operator">=</span> Date<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

  <span class="token comment">// 为 req 对象，挂载自定义属性，从而把时间共享给后面的所有路由</span>
  req<span class="token punctuation">.</span>startTime <span class="token operator">=</span> time
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home page'</span> <span class="token operator">+</span> req<span class="token punctuation">.</span>startTime<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'User page'</span> <span class="token operator">+</span> req<span class="token punctuation">.</span>startTime<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_3-9-定义多个全局中间件"><a href="#_3-9-定义多个全局中间件" class="header-anchor">#</a> 3. 9 定义多个全局中间件</h4> <ol><li><p>可以使用 <code>app.use()</code> 连续定义多个全局中间件，客户端请求到达服务器之后，会按照中间件定义的先后顺序依次执行</p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 第一个全局中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'调用了第一个全局的中间件'</span><span class="token punctuation">)</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 第二个全局中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'调用了第二个全局的中间件'</span><span class="token punctuation">)</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 定义路由</span>
<span class="token comment">// 请求这两个路由，会依次触发上述两个全局中间件</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'User Page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_3-10-局部生效的中间件"><a href="#_3-10-局部生效的中间件" class="header-anchor">#</a> 3.10 局部生效的中间件</h4> <ol><li><p>不使用 <code>app.use()</code> 定义的中间件，叫做局部生效的中间件</p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 定义中间件函数 mv1</span>
<span class="token keyword">const</span> <span class="token function-variable function">mv1</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'这是中间件函数'</span><span class="token punctuation">)</span>

  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// mv1 这个中间件只在 &quot;当前路由中生效&quot;，这种用法属于 &quot;局部生效的中间件&quot;</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> mv1<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home Page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'User Page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_3-11-定义多个局部中间件"><a href="#_3-11-定义多个局部中间件" class="header-anchor">#</a> 3.11 定义多个局部中间件</h4> <ol><li><p>可以在路由中，通过如下两种等价的方式，使用多个局部中间件</p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 定义中间件函数 mv1</span>
<span class="token keyword">const</span> <span class="token function-variable function">mv1</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'这是第一个中间件函数'</span><span class="token punctuation">)</span>

  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// 定义中间件函数 mv2</span>
<span class="token keyword">const</span> <span class="token function-variable function">mv2</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'这是第二个中间件函数'</span><span class="token punctuation">)</span>

  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// mv1、mv2 这个中间件只在 &quot;当前路由中生效&quot;，这种用法属于 &quot;局部生效的中间件&quot;</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> mv1<span class="token punctuation">,</span> mv2<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home Page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 也可以使用数组的形式绑定两个中间件</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>mv1<span class="token punctuation">,</span> mv2<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home Page'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_3-12-中间件的5个使用注意事项"><a href="#_3-12-中间件的5个使用注意事项" class="header-anchor">#</a> 3.12 中间件的5个使用注意事项</h4> <ol><li>一定要在路由之前注册中间件</li> <li>客户端发送过来的请求，可以连续调用多个中间件进行处理</li> <li>执行完中间件的业务代码之后，不要忘记调用 <code>next()</code> 函数</li> <li>为了防止代码逻辑混乱，调用 <code>next()</code> 函数后不要再写额外的代码</li> <li>连续调用多个中间件时，多个中间件之间，共享 <code>req</code> 和 <code>res</code> 对象</li></ol> <h3 id="_4-中间件的分类"><a href="#_4-中间件的分类" class="header-anchor">#</a> 4. 中间件的分类</h3> <h4 id="_4-1-中间件的分类"><a href="#_4-1-中间件的分类" class="header-anchor">#</a> 4.1 中间件的分类</h4> <h5 id="_4-1-1-中间件的分类"><a href="#_4-1-1-中间件的分类" class="header-anchor">#</a> 4.1.1 中间件的分类</h5> <ol><li>为了方便大家理解和记忆中间件的使用，Express 官方把常见的中间件用法，分成了 5 大类，分别是</li></ol> <ul><li>应用级别的中间件</li> <li>路由级别的中间件</li> <li>错误级别的中间件</li> <li>Express 内置的中间件</li> <li>第三方的中间件</li></ul> <h5 id="_4-1-2-什么是应用级别的中间件"><a href="#_4-1-2-什么是应用级别的中间件" class="header-anchor">#</a> 4.1.2 什么是应用级别的中间件</h5> <p>通过 <code>app.use()</code> 或 <code>app.get()</code> 或 <code>app.post()</code> ，<strong>绑定到 <code>app</code> 实例上的中间件</strong>，叫做应用级别的中间件</p> <img src="/heima2020/assets/img/010 - 应用级别的中间件.441f6b45.png" style="zoom:67%;"> <h5 id="_4-1-3-什么是路由级别的中间件"><a href="#_4-1-3-什么是路由级别的中间件" class="header-anchor">#</a> 4.1.3 什么是路由级别的中间件</h5> <ol><li><p>绑定到 <code>express.Router()</code> 实例上的中间件，叫做路由级别的中间件</p></li> <li><p>用法上和应用级别中间件没有任何区别，只不过，应用级别中间件是绑定到 <code>app</code> 实例上，路由级别中间件绑定到 <code>router</code> 实例上</p></li></ol> <img src="/heima2020/assets/img/011 - 路由级别的中间件.07780164.png" style="zoom:85%;"> <h4 id="_4-2-错误级别中间件"><a href="#_4-2-错误级别中间件" class="header-anchor">#</a> 4.2 错误级别中间件</h4> <ol><li><p>错误级别中间件的作用： 专门用来捕获整个项目中发生的异常错误，从而防止项目异常崩溃的问题</p></li> <li><p>格式：错误级别中间件的 function 处理函数中，必须有 4 个形参，形参顺序从前到后，分别是<code>(err, req, res, next)</code></p></li> <li><p><strong>注意： 错误级别的中间件，必须注册在所有路由之后</strong></p></li> <li><p>案例代码：</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 1. 路由</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 1.1 抛出一个自定义的错误</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">'服务器内部发生了错误'</span><span class="token punctuation">)</span>

  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'Home Page.'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 2. 错误级别的中间件</span>
<span class="token comment">// 注意：错误级别的中间件，必须注册在所有路由之后</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 2.1 在服务器打印错误消息</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'发生了错误：'</span> <span class="token operator">+</span> err<span class="token punctuation">.</span>message<span class="token punctuation">)</span>

  <span class="token comment">// 2.2 向客户端响应错误相关的内容 </span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>err<span class="token punctuation">.</span>message<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_4-3-express内置的中间件"><a href="#_4-3-express内置的中间件" class="header-anchor">#</a> 4.3 Express内置的中间件</h4> <p>自 <code>Express 4.16.0</code> 版本开始，<code>Express</code> 内置了 3 个常用的中间件，极大的提高了 <code>Express</code> 项目的开发效率和体验</p> <ol><li><p><code>express.static</code> 快速托管静态资源的内置中间件，例如： HTML 文件、图片、<code>CSS</code> 样式等（无兼容性）</p></li> <li><p><code>express.json</code> 解析 <code>JSON</code> 格式的请求体数据（<strong>有兼容性</strong>，仅在 <code>4.16.0+</code> 版本中可用）</p></li> <li><p><code>express.urlencoded</code> 解析 <code>URL-encoded</code> 格式的请求体数据（<strong>有兼容性</strong>，仅在 <code>4.16.0+</code> 版本中可用）</p></li></ol> <img src="/heima2020/assets/img/012 - Express内置的中间件.86e03e63.png" style="zoom:67%;"> <h4 id="_4-4-express-json-中间件的使用"><a href="#_4-4-express-json-中间件的使用" class="header-anchor">#</a> 4.4 <code>express.json</code> 中间件的使用</h4> <ol><li><p><code>express.json()</code>  中间件，解析表单中的 <code>JSON</code> 格式的数据</p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 注意：除了错误级别的中间件，其他的中间件，必须在路由之前进行配置</span>
<span class="token comment">// 通过 express.json() 这个中间件，解析表单中的 JSON 格式的数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 在服务器，可以使用 req.body 这个属性，来接收客户端发送过来的请求体数据</span>
  <span class="token comment">// 默认情况下，如果不配置解析表单数据中间件，则 req.body 默认等于 undefined</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_4-5-express-urlencoded-中间件的使用"><a href="#_4-5-express-urlencoded-中间件的使用" class="header-anchor">#</a> 4.5 <code>express.urlencoded</code> 中间件的使用</h4> <ol><li><p><code>express.urlencoded</code> 解析 <code>URL-encoded</code> 格式的请求体数据</p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 通过 express.urlencoded() 这个中间件，来解析表单中的 url-encoded 格式的数据</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/book'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_4-6-第三方的中间件"><a href="#_4-6-第三方的中间件" class="header-anchor">#</a> 4.6 第三方的中间件</h4> <h5 id="_4-6-1-什么是第三方中间件"><a href="#_4-6-1-什么是第三方中间件" class="header-anchor">#</a> 4.6.1 什么是第三方中间件</h5> <ol><li><p>非 <code>Express</code> 官方内置，而是由第三方开发出来的中间件，叫做第三方中间件。在项目中，大家可以按需下载并配置第三方中间件，从而提高项目的开发效率</p></li> <li><p>例如：在 <code>express@4.16.0</code> 之前的版本中，经常使用 <code>body-parser</code> 这个第三方中间件，来解析请求体数据。使用步骤如下</p> <ul><li>运行 <code>npm install body-parser</code> 安装中间件</li> <li>使用 <code>require</code> 导入中间件</li> <li>调用 <code>app.use()</code> 注册并使用中间件</li></ul></li> <li><p><strong>注意：<code>Express</code> 内置的 <code>express.urlencoded</code> 中间件，就是基于 <code>body-parser</code> 这个第三方中间件进一步封装出来的</strong></p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 1. 导入解析表单数据的中间件 body-parser</span>
<span class="token keyword">const</span> bodyParser <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'body-parser'</span><span class="token punctuation">)</span>

<span class="token comment">// 通过 express.urlencoded() 这个中间件，来解析表单中的 url-encoded 格式的数据</span>
<span class="token comment">// app.use(express.urlencoded({ extended: false }))</span>

<span class="token comment">// 2. 使用 app.use() 注册中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>bodyParser<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/book'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h3 id="_5-自定义中间件"><a href="#_5-自定义中间件" class="header-anchor">#</a> 5. 自定义中间件</h3> <h4 id="_5-1-需求描述与实现步骤"><a href="#_5-1-需求描述与实现步骤" class="header-anchor">#</a> 5.1 需求描述与实现步骤</h4> <h5 id="_5-1-1-需求以及实现步骤"><a href="#_5-1-1-需求以及实现步骤" class="header-anchor">#</a> 5.1.1 需求以及实现步骤</h5> <ol><li>需求描述： 自己手动模拟一个类似于 <code>express.urlencoded</code> 这样的中间件，来解析 <strong><code>POST 提交到服务器的表单数据</code></strong></li> <li>实现步骤：</li></ol> <ul><li>定义中间件</li> <li>监听 <code>req</code> 的 <code>data</code> 事件</li> <li>监听 <code>req</code> 的 <code>end</code> 事件</li> <li>使用 <code>querystring</code> 模块解析请求体数据</li> <li>将解析出来的数据对象挂载为 <code>req.body</code></li> <li>将自定义中间件封装为模块</li></ul> <h5 id="_5-1-2-定义中间件"><a href="#_5-1-2-定义中间件" class="header-anchor">#</a> 5.1.2 定义中间件</h5> <ol><li><p>使用 <code>app.use()</code> 来定义全局生效的中间件</p></li> <li><p>代码如下：</p></li></ol> <img src="/heima2020/assets/img/013 - 定义中间件.92fbc302.png" style="zoom:67%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义中间价具体的业务逻辑</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-2-监听-req-的-data-事件"><a href="#_5-2-监听-req-的-data-事件" class="header-anchor">#</a> 5.2  监听 <code>req</code> 的 <code>data</code> 事件</h4> <ol><li><p>在中间件中，需要监听 <code>req</code> 对象的 <code>data</code> 事件，来获取客户端发送到服务器的数据</p></li> <li><p>如果数据量比较大，无法一次性发送完毕，则客户端会把数据切割后，分批发送到服务器。所以 <code>data</code> 事件可能会触发多次，每一次触发 <code>data</code> 事件时，获取到数据只是完整数据的一部分，需要手动对接收到的数据进行拼接</p></li> <li><p>代码如下：</p> <img src="/heima2020/assets/img/014 - 监听 req 的 data 事件.1e5d5ed7.png" style="zoom:80%;"></li> <li><p>案例代码</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义中间价具体的业务逻辑</span>
  <span class="token comment">// 1. 定义一个 str 字符串，专门用来存储客户端发送过来的请求体数据</span>
  <span class="token keyword">let</span> str <span class="token operator">=</span> <span class="token string">''</span>
  <span class="token comment">// 2. 监听 req 的 data 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'data'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">chunk</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    str <span class="token operator">+=</span> chunk
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div></li></ol> <h4 id="_5-3-监听-req-的-end-事件"><a href="#_5-3-监听-req-的-end-事件" class="header-anchor">#</a> 5.3 监听 <code>req</code> 的 <code>end</code> 事件</h4> <ol><li><p>当请求体数据接收完毕之后，会自动触发 <code>req</code> 的 <code>end</code> 事件</p></li> <li><p>我们可以在 <code>req</code> 的 <code>end</code> 事件中，拿到并处理完整的请求体数据</p></li> <li><p>代码如下</p></li></ol> <img src="/heima2020/assets/img/015 - 监听 req 的 end 事件.c690b0b2.png" style="zoom:67%;"> <ol start="4"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义中间价具体的业务逻辑</span>
  <span class="token comment">// 1. 定义一个 str 字符串，专门用来存储客户端发送过来的请求体数据</span>
  <span class="token keyword">let</span> str <span class="token operator">=</span> <span class="token string">''</span>
  <span class="token comment">// 2. 监听 req 的 data 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'data'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">chunk</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    str <span class="token operator">+=</span> chunk
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token comment">// 3. 监听 req 的 end 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在 str 中存放的是完整的请求体数据</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>
    <span class="token comment">// 将字符串格式的请求体数据，解析成对象</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-4-用-querystring-模块解析请求体数据"><a href="#_5-4-用-querystring-模块解析请求体数据" class="header-anchor">#</a> 5.4 用 <code>querystring</code> 模块解析请求体数据</h4> <ol><li><p><code>Node.js</code> 内置了一个 <code>querystring</code> 模块，专门用来处理查询字符串。通过这个模块提供的 <code>parse()</code> 函数，可以轻松把查询字符串，解析成对象的格式</p></li> <li><p>代码如下</p></li></ol> <img src="/heima2020/assets/img/016 - 使用 querystring 模块解析请求体数据.1c752c9a.png" style="zoom:67%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 4. 导入 Node 内置模块 querystring</span>
<span class="token keyword">const</span> qs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'querystring'</span><span class="token punctuation">)</span>

<span class="token comment">// 解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义中间价具体的业务逻辑</span>
  <span class="token comment">// 1. 定义一个 str 字符串，专门用来存储客户端发送过来的请求体数据</span>
  <span class="token keyword">let</span> str <span class="token operator">=</span> <span class="token string">''</span>
  <span class="token comment">// 2. 监听 req 的 data 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'data'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">chunk</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    str <span class="token operator">+=</span> chunk
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token comment">// 3. 监听 req 的 end 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在 str 中存放的是完整的请求体数据</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>
    <span class="token comment">// 将字符串格式的请求体数据，解析成对象</span>
    <span class="token comment">// 5. 调用 qs.parse() 方法，将查询字符串解析成对象</span>
    <span class="token keyword">const</span> body <span class="token operator">=</span>  qs<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>body<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token string">'ok'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-5-将解析出来的数据对象挂载为-req-body"><a href="#_5-5-将解析出来的数据对象挂载为-req-body" class="header-anchor">#</a> 5.5 将解析出来的数据对象挂载为 <code>req.body</code></h4> <ol><li><p><strong>上游的中间件和下游的中间件及路由之间，共享同一份 <code>req</code> 和 <code>res</code></strong>，因此，我们可以将解析出来的数据，挂载为 <code>req</code> 的自定义属性，命名为 <code>req.body</code>，供下游使用</p></li> <li><p>代码如下</p></li></ol> <img src="/heima2020/assets/img/017 - 将解析出来的数据对象挂载为 req.body.7b8f6058.png" style="zoom:67%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// 4. 导入 Node 内置模块 querystring</span>
<span class="token keyword">const</span> qs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'querystring'</span><span class="token punctuation">)</span>

<span class="token comment">// 解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义中间价具体的业务逻辑</span>
  <span class="token comment">// 1. 定义一个 str 字符串，专门用来存储客户端发送过来的请求体数据</span>
  <span class="token keyword">let</span> str <span class="token operator">=</span> <span class="token string">''</span>
  <span class="token comment">// 2. 监听 req 的 data 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'data'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">chunk</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    str <span class="token operator">+=</span> chunk
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token comment">// 3. 监听 req 的 end 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在 str 中存放的是完整的请求体数据</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>
    <span class="token comment">// 将字符串格式的请求体数据，解析成对象</span>
    <span class="token comment">// 5. 调用 qs.parse() 方法，将查询字符串解析成对象</span>
    <span class="token keyword">const</span> body <span class="token operator">=</span>  qs<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>

    <span class="token comment">// 6. 将解析出来的数据对象挂载为 req.body 属性</span>
    req<span class="token punctuation">.</span>body <span class="token operator">=</span> body
    <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_5-6-将自定义中间件封装为模块"><a href="#_5-6-将自定义中间件封装为模块" class="header-anchor">#</a> 5.6  将自定义中间件封装为模块</h4> <ol><li><p>为了优化代码的结构，我们可以把自定义的中间件函数，封装为独立的模块</p></li> <li><p>代码如下：</p></li></ol> <img src="/heima2020/assets/img/018 - 将自定义中间件封装为模块.bba9adac.png" style="zoom:80%;"> <ol start="3"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// custom-body-parser.js</span>

<span class="token keyword">const</span> qs <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'querystring'</span><span class="token punctuation">)</span>

<span class="token keyword">const</span> <span class="token function-variable function">bodyParser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res<span class="token punctuation">,</span> next</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义中间价具体的业务逻辑</span>
  <span class="token comment">// 1. 定义一个 str 字符串，专门用来存储客户端发送过来的请求体数据</span>
  <span class="token keyword">let</span> str <span class="token operator">=</span> <span class="token string">''</span>
  <span class="token comment">// 2. 监听 req 的 data 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'data'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">chunk</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    str <span class="token operator">+=</span> chunk
  <span class="token punctuation">}</span><span class="token punctuation">)</span>

  <span class="token comment">// 3. 监听 req 的 end 事件</span>
  req<span class="token punctuation">.</span><span class="token function">on</span><span class="token punctuation">(</span><span class="token string">'end'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// 在 str 中存放的是完整的请求体数据</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>
    <span class="token comment">// 将字符串格式的请求体数据，解析成对象</span>
    <span class="token comment">// 5. 调用 qs.parse() 方法，将查询字符串解析成对象</span>
    <span class="token keyword">const</span> body <span class="token operator">=</span>  qs<span class="token punctuation">.</span><span class="token function">parse</span><span class="token punctuation">(</span>str<span class="token punctuation">)</span>

    <span class="token comment">// 6. 将解析出来的数据对象挂载为 req.body 属性</span>
    req<span class="token punctuation">.</span>body <span class="token operator">=</span> body
    <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> bodyParser

</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 对自定义的中间件进行模块化拆分</span>

<span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 1. 导入自己封装的中间件模块</span>
<span class="token keyword">const</span> customBodyParser <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./017-custom-body-parser'</span><span class="token punctuation">)</span>
<span class="token comment">// 2. 将自定义的中间件函数，注册为全局可用的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>customBodyParser<span class="token punctuation">)</span>

app<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/user'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>req<span class="token punctuation">.</span>body<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h3 id="_6-基于-express-写接口"><a href="#_6-基于-express-写接口" class="header-anchor">#</a> 6. 基于 Express 写接口</h3> <h4 id="_6-1-创建基本的服务器"><a href="#_6-1-创建基本的服务器" class="header-anchor">#</a> 6.1 创建基本的服务器</h4> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_6-2-创建-api-路由模块"><a href="#_6-2-创建-api-路由模块" class="header-anchor">#</a> 6.2 创建 API 路由模块</h4> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// router.js</span>

<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 在这里挂载对应的路由</span>


module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// index.js</span>

<span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入路由模块</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./router.js'</span><span class="token punctuation">)</span>
<span class="token comment">// 把路由模块，注册到 app 上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> router<span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_6-3-编写-get-请求"><a href="#_6-3-编写-get-请求" class="header-anchor">#</a> 6.3 编写 get 请求</h4> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 在这里挂载对应的路由</span>
router<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/book'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 通过 req.query 获取客户端通过查询字符串发送到服务器的数据</span>
  <span class="token keyword">const</span> query <span class="token operator">=</span> req<span class="token punctuation">.</span>query

  <span class="token comment">// 调用 res.send() 方法，想客户端响应处理的结果</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>  <span class="token comment">// 0 表示处理成功，1 表示处理失败</span>
    msg<span class="token operator">:</span> <span class="token string">'GET 请求成功'</span><span class="token punctuation">,</span>  <span class="token comment">// 状态描述</span>
    data<span class="token operator">:</span> query <span class="token comment">// 需要响应给客户端的数据</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><h4 id="_6-4-编写-post-请求"><a href="#_6-4-编写-post-请求" class="header-anchor">#</a> 6.4 编写 post 请求</h4> <p><strong>注意：如果要获取 URL-encoded 格式的请求体数据，必须配置中间件 <code>app.use(express.urlencoded({ extended: false }))</code></strong></p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> express<span class="token punctuation">.</span><span class="token function">Router</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 在这里挂载对应的路由</span>

<span class="token comment">// 定义 POST 接口</span>
router<span class="token punctuation">.</span><span class="token function">post</span><span class="token punctuation">(</span><span class="token string">'/book'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 通过 req.body 获取请求题中包含的 url-encoded 格式的数据</span>
  <span class="token keyword">const</span> body <span class="token operator">=</span> req<span class="token punctuation">.</span>body

  <span class="token comment">// 调用 res.send() 方法，向客户端响应结果</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
    status<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
    msg<span class="token operator">:</span> <span class="token string">'Post 请求成功'</span><span class="token punctuation">,</span>
    data<span class="token operator">:</span> body
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

module<span class="token punctuation">.</span>exports <span class="token operator">=</span> router

</code></pre></div><div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// index.js</span>
<span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 配置解析表单数据的中间件</span>
<span class="token comment">//注意：如果要获取 URL-encoded 格式的请求体数据，必须配置中间件 app.use(express.urlencoded({ extended: false }))</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 导入路由模块</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./020-apiRouter'</span><span class="token punctuation">)</span>
<span class="token comment">// 把路由模块，注册到 app 上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> router<span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h3 id="_7-cors"><a href="#_7-cors" class="header-anchor">#</a> 7. <code>cors</code></h3> <h4 id="_7-1-接口的跨域问题"><a href="#_7-1-接口的跨域问题" class="header-anchor">#</a> 7.1  接口的跨域问题</h4> <ol><li><p>到目前为止，我们编写的 <code>GET</code> 和 <code>POST</code> 接口，存在一个很严重的问题：<strong>不支持跨域请求</strong></p></li> <li><p>解决接口跨域问题的方案主要有两种</p></li></ol> <ul><li><strong>CORS</strong>  (主流的解决方案，推荐使用)</li> <li><strong>JSONP</strong>  (有缺陷的解决方案：只支持 GET 请求)</li></ul> <ol start="3"><li>代码演示</li></ol> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>en<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>viewport<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>width=device-width, initial-scale=1.0<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Document<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>btn1<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>get<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>btn2<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>post<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">&gt;</span></span>

  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.btn1'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        $<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          url<span class="token operator">:</span> <span class="token string">'http://127.0.0.1:3000/api/book?name=tom&amp;age=10'</span><span class="token punctuation">,</span>
          <span class="token function-variable function">success</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>

      <span class="token function">$</span><span class="token punctuation">(</span><span class="token string">'.btn2'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">click</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        $<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
          url<span class="token operator">:</span> <span class="token string">'http://127.0.0.1:3000/api/book'</span><span class="token punctuation">,</span>
          method<span class="token operator">:</span> <span class="token string">'post'</span><span class="token punctuation">,</span>
          data<span class="token operator">:</span> <span class="token punctuation">{</span>
            name<span class="token operator">:</span> <span class="token string">'雪中悍刀行'</span><span class="token punctuation">,</span>
            author<span class="token operator">:</span> <span class="token string">'烽火戏诸侯'</span>
          <span class="token punctuation">}</span><span class="token punctuation">,</span>
          <span class="token function-variable function">success</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span>
          <span class="token punctuation">}</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div><ol start="4"><li>报错提示</li></ol> <img src="/heima2020/assets/img/019 - 跨域.71a34830.png" style="zoom:200%;"> <h4 id="_7-2-使用-cors-中间件解决跨域问题"><a href="#_7-2-使用-cors-中间件解决跨域问题" class="header-anchor">#</a> 7.2 使用 cors 中间件解决跨域问题</h4> <ol><li><p>cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件，可以很方便地解决跨域问题</p></li> <li><p>使用步骤</p> <ul><li>安装中间件： <code>npm install cors</code></li> <li>导入中间件： <code>const cors = require('cors')</code></li> <li>配置中间件： 在路由之前调用<code>app.use(cors())</code></li></ul></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 导入中间件</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
<span class="token comment">// 配置中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 配置解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 导入路由模块</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./020-apiRouter'</span><span class="token punctuation">)</span>
<span class="token comment">// 把路由模块，注册到 app 上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> router<span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><ol start="4"><li>配置 <code>cors</code> 插件后</li></ol> <img src="/heima2020/assets/img/020 - cors.e4e48193.png" style="zoom:80%;"> <h4 id="_7-3-什么是-cors-以及注意事项"><a href="#_7-3-什么是-cors-以及注意事项" class="header-anchor">#</a> 7.3  什么是 CORS 以及注意事项</h4> <h5 id="_7-3-1-什么是-cors"><a href="#_7-3-1-什么是-cors" class="header-anchor">#</a> 7.3.1 什么是 CORS</h5> <ol><li><p><code>CORS</code> (跨域资源共享) 由一系列 <code>HTTP</code> 响应头组成，这些 <code>HTTP</code> 响应头决定浏览器 <strong>是否阻止前端 JS 代码跨域获取资源</strong></p></li> <li><p>浏览器的<strong>同源安全策略</strong>默认会阻止网页“跨域”获取资源。但如果接口服务器<strong>配置了 CORS 相关的 HTTP 响应头</strong>，就可以<strong>解除浏览器端的跨域访问限制</strong></p></li></ol> <img src="/heima2020/assets/img/021 - 什么是 CORS.4bd98ac0.png" style="zoom:80%;"> <h5 id="_7-3-2-cors-的注意事项"><a href="#_7-3-2-cors-的注意事项" class="header-anchor">#</a> 7.3.2  CORS 的注意事项</h5> <ol><li><code>CORS</code> 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置，即可请求开启了 <code>CORS</code> 的接口</li> <li><code>CORS</code> 在浏览器中有兼容性。只有支持 <code>XMLHttpRequest Level2</code> 的浏览器，才能正常访问开启了 <code>CORS</code> 的服务端接口（例如：<code>IE10+</code>、<code>Chrome4+</code>、<code>FireFox3.5+</code>）</li></ol> <h4 id="_7-4-了解-access-control-allow-origin"><a href="#_7-4-了解-access-control-allow-origin" class="header-anchor">#</a> 7.4 了解 Access-Control-Allow-Origin</h4> <ol><li>响应头部中可以携带一个 <code>Access-Control-Allow-Origin</code> 字段</li></ol> <img src="/heima2020/assets/img/022 - Access-Control-Allow-Origin.58f69d07.png" alt="Access-Control-Allow-Origin" style="zoom:67%;"> <ol start="2"><li><p><code>origin</code> 参数的值指定了允许访问该资源的外域 <code>URL</code></p></li> <li><p>例如，下面的字段值将只允许来自 http://itcast.cn 的请求</p></li></ol> <img src="/heima2020/assets/img/023 -  Access-Control-Allow-Origin.1b541c16.png" style="zoom:67%;"> <ol start="4"><li><p>如果指定了 <code>Access-Control-Allow-Origin</code> 字段的值为通配符 *，表示允许来自任何域的请求</p> <img src="/heima2020/assets/img/024 - Access-Control-Allow-Origin.57b0aa93.png" style="zoom:67%;"></li></ol> <h4 id="_7-5-了解-access-control-allow-headers"><a href="#_7-5-了解-access-control-allow-headers" class="header-anchor">#</a> 7.5 了解  Access-Control-Allow-Headers</h4> <ol><li><p>默认情况下，CORS 仅支持客户端向服务器发送如下的 9 个请求头</p> <ul><li><code>Accept</code></li> <li><code>Accept-Language</code></li> <li><code>Content-Language</code></li> <li><code>DPR</code></li> <li><code>Downlink</code></li> <li><code>Save-Data</code></li> <li><code>Viewport-Width</code></li> <li><code>Width</code></li> <li><code>Content-Type</code> （值仅限于 <code>text/plain</code>、<code>multipart/form-data</code>、<code>application/x-www-form-urlencoded</code> 三者之一）</li></ul></li> <li><p>如果客户端向服务器发送了额外的请求头信息，则需要在服务器端，通过 <code>Access-Control-Allow-Headers</code> 对额外的请求头进行声明，否则这次请求会失败！</p></li></ol> <img src="/heima2020/assets/img/025 - Access-Control-Allow-Headers.599973ed.png" style="zoom:67%;"> <h4 id="_7-6-了解-access-control-allow-methods"><a href="#_7-6-了解-access-control-allow-methods" class="header-anchor">#</a> 7.6 了解  Access-Control-Allow-Methods</h4> <ol><li><p>默认情况下，<code>CORS</code> 仅支持客户端发起 <code>GET</code>、<code>POST</code>、<code>HEAD</code> 请求</p></li> <li><p>如果客户端希望通过 <code>PUT</code>、<code>DELETE</code> 等方式请求服务器的资源，则需要在服务器端，通过 <code>Access-Control-Alow-Methods</code> 来指明实际请求所允许使用的 <code>HTTP</code> 方法</p> <img src="/heima2020/assets/img/026 - Access-Control-Allow-Methods.b7358cf7.png" style="zoom:67%;"></li></ol> <h4 id="_7-7-cors-请求的分类"><a href="#_7-7-cors-请求的分类" class="header-anchor">#</a> 7.7 CORS 请求的分类</h4> <h5 id="_7-7-1-cors请求的分类"><a href="#_7-7-1-cors请求的分类" class="header-anchor">#</a> 7.7.1 CORS请求的分类</h5> <ol><li>客户端在请求 CORS 接口时，根据请求方式和请求头的不同，可以将 CORS 的请求分为两大类，分别是：</li></ol> <ul><li>简单请求</li> <li>预检请求</li></ul> <h5 id="_7-2-2-简单请求"><a href="#_7-2-2-简单请求" class="header-anchor">#</a> 7.2.2 简单请求</h5> <ol><li>同时满足以下两大条件的请求，就属于简单请求</li></ol> <ul><li><strong>请求方式</strong>：<code>GET</code>、<code>POST</code>、<code>HEAD</code> 三者之一</li> <li>HTTP 头部信息不超过以下几种字段：
<ul><li>无自定义头部字段</li> <li><code>Accept</code></li> <li><code>Accept-Language</code></li> <li><code>Content-Language</code></li> <li><code>DPR</code></li> <li><code>Downlink</code></li> <li><code>Save-Data</code></li> <li><code>Viewport-Width</code></li> <li><code>Width</code></li> <li><code>Content-Type</code>（只有三个值 <code>application/x-www-form-urlencoded</code>、<code>multipart/form-data</code>、<code>text/plain</code>）</li></ul></li></ul> <h5 id="_7-3-3-预检请求"><a href="#_7-3-3-预检请求" class="header-anchor">#</a> 7.3.3 预检请求</h5> <ol><li>只要符合以下任何一个条件的请求，都需要进行预检请求</li></ol> <ul><li>请求方式为 <code>GET</code>、<code>POST</code>、<code>HEAD</code> 之外的请求 <code>Method</code> 类型</li> <li>请求头中包含自定义头部字段</li> <li>向服务器发送了 <code>application/json</code> 格式的数据</li></ul> <ol start="2"><li>在浏览器与服务器正式通信之前，浏览器会<strong>先发送 OPTION 请求进行预检，以获知服务器是否允许该实际请求</strong>，所以这一次的 OPTION 请求称为“预检请求”。<strong>服务器成功响应预检请求后，才会发送真正的请求，并且携带真实数据</strong></li></ol> <h4 id="_7-4-简单请求和预检请求的区别"><a href="#_7-4-简单请求和预检请求的区别" class="header-anchor">#</a> 7.4 简单请求和预检请求的区别</h4> <ol><li>简单请求的特点：客户端与服务器之间<strong>只会发生一次请求</strong></li> <li>预检请求的特点：客户端与服务器之间<strong>会发生两次请求，OPTION 预检请求成功之后，才会发起真正的请求</strong></li></ol> <h3 id="_8-jsonp"><a href="#_8-jsonp" class="header-anchor">#</a> 8. <code>jsonp</code></h3> <h4 id="_8-1-回顾-jsonp-的概念与特点"><a href="#_8-1-回顾-jsonp-的概念与特点" class="header-anchor">#</a> 8.1 回顾 <code>JSONP</code> 的概念与特点</h4> <ol><li>概念：浏览器端通过 <code>&lt;script&gt;</code> 标签的 <code>src</code> 属性，请求服务器上的数据，同时，服务器返回一个函数的调用。这种请求数据的方式叫做 <code>JSONP</code></li> <li>特点</li></ol> <ul><li><code>JSONP</code> 不属于真正的 <code>Ajax</code> 请求，因为它没有使用 <code>XMLHttpRequest</code> 这个对象</li> <li><code>JSONP</code> 仅支持 <code>GET</code> 请求，不支持 <code>POST</code>、<code>PUT</code>、<code>DELETE</code> 等请求</li></ul> <h4 id="_8-2-创建-jsonp-接口的注意事项"><a href="#_8-2-创建-jsonp-接口的注意事项" class="header-anchor">#</a> 8.2 创建 <code>JSONP</code> 接口的注意事项</h4> <ol><li><p>如果项目中已经配置了 <code>CORS</code> 跨域资源共享，为了防止冲突，必须在配置 <code>CORS</code> 中间件之前声明 <code>JSONP</code> 的接口</p> <p>否则 <code>JSONP</code> 接口会被处理成开启了 <code>CORS</code> 的接口</p></li> <li><p>案例代码</p></li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 配置解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 必须在配置 cors 中间件之前，配置 JSONP 的接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/jsonp'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义 JSONP 接口具体的实现过程</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 导入中间件</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 导入路由模块</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./020-apiRouter'</span><span class="token punctuation">)</span>
<span class="token comment">// 把路由模块，注册到 app 上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> router<span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_8-3-实现-jsonp-接口的步骤"><a href="#_8-3-实现-jsonp-接口的步骤" class="header-anchor">#</a> 8.3 实现 <code>JSONP</code> 接口的步骤</h4> <h5 id="_8-3-1-实现步骤分析"><a href="#_8-3-1-实现步骤分析" class="header-anchor">#</a> 8.3.1 实现步骤分析</h5> <ol><li>获取客户端发送过来的回调函数的名字</li> <li>得到要通过 <code>JSONP</code> 形式发送给客户端的数据</li> <li>根据前两步得到的数据，拼接出一个函数调用的字符串</li> <li>把上一步拼接得到的字符串，响应给客户端的 <code>&lt;script&gt;</code> 标签进行解析执行</li></ol> <h5 id="_8-3-2-案例代码"><a href="#_8-3-2-案例代码" class="header-anchor">#</a> 8.3.2  案例代码</h5> <ol><li>实现步骤</li></ol> <img src="/heima2020/assets/img/027 - 实现 JSONP接口的步骤.25b518f1.png" style="zoom:67%;"> <ol start="2"><li>案例代码</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 导入 express 模块</span>
<span class="token keyword">const</span> express <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'express'</span><span class="token punctuation">)</span>

<span class="token comment">// 创建 express 的服务器实例</span>
<span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">express</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 配置解析表单数据的中间件</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span>express<span class="token punctuation">.</span><span class="token function">urlencoded</span><span class="token punctuation">(</span><span class="token punctuation">{</span> extended<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 必须在配置 cors 中间件之前，配置 JSONP 的接口</span>
app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/api/jsonp'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">req<span class="token punctuation">,</span> res</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 定义 JSONP 接口具体的实现过程</span>
  <span class="token comment">// 1. 得到函数的名称</span>
  <span class="token keyword">const</span> funcName <span class="token operator">=</span> req<span class="token punctuation">.</span>query<span class="token punctuation">.</span>callback
  <span class="token comment">// 2. 定义要发送到客户端的数据对象</span>
  <span class="token keyword">const</span> data <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'zs'</span><span class="token punctuation">,</span> age<span class="token operator">:</span> <span class="token number">11</span> <span class="token punctuation">}</span>
  <span class="token comment">// 3. 拼接处一个函数的调用</span>
  <span class="token keyword">const</span> scriptStr <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>funcName<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span><span class="token constant">JSON</span><span class="token punctuation">.</span><span class="token function">stringify</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">)</span><span class="token template-punctuation string">`</span></span>
  <span class="token comment">// 4. 把拼接的字符串，响应给客户端</span>
  res<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>scriptStr<span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 导入中间件</span>
<span class="token keyword">const</span> cors <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'cors'</span><span class="token punctuation">)</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token function">cors</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// 导入路由模块</span>
<span class="token keyword">const</span> router <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'./020-apiRouter'</span><span class="token punctuation">)</span>
<span class="token comment">// 把路由模块，注册到 app 上</span>
app<span class="token punctuation">.</span><span class="token function">use</span><span class="token punctuation">(</span><span class="token string">'/api'</span><span class="token punctuation">,</span> router<span class="token punctuation">)</span>

<span class="token comment">// 调用 app.listen 方法，指定端口号并启动 web 服务器</span>
app<span class="token punctuation">.</span><span class="token function">listen</span><span class="token punctuation">(</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'running……'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre></div><h4 id="_8-4-在网页中使用-jquery-发起-jsonp-请求"><a href="#_8-4-在网页中使用-jquery-发起-jsonp-请求" class="header-anchor">#</a> 8.4  在网页中使用 jQuery 发起 JSONP 请求</h4> <ol><li>调用 $.ajax() 函数，提供 JSONP 的配置选项，从而发起 JSONP 请求</li></ol> <div class="language-html extra-class"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>en<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>viewport<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>width=device-width, initial-scale=1.0<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Document<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span><span class="token script"></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>script</span><span class="token punctuation">&gt;</span></span><span class="token script"><span class="token language-javascript">
    <span class="token function">$</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      $<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
        method<span class="token operator">:</span> <span class="token string">'GET'</span><span class="token punctuation">,</span>
        url<span class="token operator">:</span> <span class="token string">'http://127.0.0.1:3000/api/jsonp'</span><span class="token punctuation">,</span>
        dataType<span class="token operator">:</span> <span class="token string">'jsonp'</span><span class="token punctuation">,</span>
        <span class="token function-variable function">success</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">res</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span>
  </span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>script</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>
</code></pre></div></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/heima2020/node/day03.html" class="prev">
        Node 第 3 天
      </a></span> <span class="next"><a href="/heima2020/node/day05.html">
        Node 第 5 天
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><!----></div></div>
    <script src="/heima2020/assets/js/app.e2adc9d2.js" defer></script><script src="/heima2020/assets/js/2.7389c9d3.js" defer></script><script src="/heima2020/assets/js/5.6eb7e243.js" defer></script>
  </body>
</html>
